home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * NNTP Server - See RFC977
- * Jeffrey R. Comstock. - NR0D - Bloomington, Minnesota USA
- * Copyright 1990 Jeffrey R. Comstock, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- *
- * DB3FL 9107xx: heavily rewritten and bug fixing in file-handling
- * DB3FL 920121: splitted into several files
- * DG1ZX 9210xx: bug fixing and optimize
- * DG1ZX 9303xx: included POST and XDHR command
- * DG1ZX 930728: included nntp restrictions and history lifetime
- *
- */
- #include <dos.h>
- #include <time.h>
- #include <ctype.h>
-
- #include "global.h"
- #include "config.h"
- #ifdef NNTP
- #include "nntp.h"
- #include "socket.h"
- #include "files.h"
- #include "ftp.h"
- #include "bm.h"
- #ifdef LZW
- #include "lzw.h"
- #endif
-
- #undef CONTROL /* (not implemented yet) */
- #define LINE 80
-
- #ifdef LZW
- int LzwActive = 1;
- #endif
-
- #ifdef POST_ENBL
- int postingok = 1;
- #endif
-
- int fullauto = 1;
- unsigned short Nntpmaxcli = 3;
- static unsigned short Nntpsessions = 0;
-
- static int Snntp = -1; /* prototype socket for service */
-
- static char artmsg[] = " Article retrieved - ";
- static char debug[] = "100 DEBUG %s\n";
-
- #if (defined(POST_ENBL) && defined(XHEADER))
- static char help[] = "100-ARTICLE BODY GROUP HEAD HELP IHAVE LAST LIST\n"
- "100 NEWNEWS NEXT POST QUIT STAT XHDR XINFO\n";
- #elif (defined(POST_ENBL))
- static char help[] = "100-ARTICLE BODY GROUP HEAD HELP IHAVE LAST\n"
- "100 LIST NEWNEWS NEXT POST QUIT STAT XINFO\n";
- #elif (defined(XHEADER))
- static char help[] = "100-ARTICLE BODY GROUP HEAD HELP IHAVE LAST\n"
- "100 LIST NEWNEWS NEXT QUIT STAT XHDR XINFO\n";
- #else
- static char help[] = "100-ARTICLE BODY GROUP HEAD HELP IHAVE\n"
- "100 LAST LIST NEWNEWS NEXT QUIT STAT XINFO\n";
- #endif
-
- /*
- static char info[] = "100 %s Info:\n";
- */
- static char xinfo[] = "100 No info available\n";
- static char noactive[] = "100 No active newsgroups\n";
-
- #ifdef POST_ENBL
- static char nnversion[] = "20%c %s NNTP version %s ready at %s GMT (posting %s)\n";
- #else
- static char nnversion[] = "201 %s NNTP version %s ready at %s GMT\n";
- #endif
- static char slave[] = "202 SLAVE %s\n";
- static char closing[] = "205 Closing\n";
- static char listarticle[] = "211 %u %u %u%s\n";
- static char listgrps[] = "215 Available newsgroups\n";
- static char retrieve[] = "220 %u%s%shead and body follow\n";
- static char head[] = "221 %u%s%sHead\n";
- #ifdef XHEADER
- static char extrfoll[] = "221 %s fields follow\n";
- #endif
- static char body[] = "222 %u%s%sBody\n";
- static char statistics[] = "223 %u%s%sStatistics\n";
- static char sepcmd[] = "223 %u %s%srequest text separately\n";
- static char newnews_t[] = "230 New news by message id follows\n";
- static char transok[] = "235 Thanks\n";
- #ifdef POST_ENBL
- static char postok[] = "240 Article posted ok\n";
- #endif
-
- static char sendart[] = "335 Send article, end with .\n";
- #ifdef POST_ENBL
- static char sendpost[] = "340 Send article to be posted, end with .\n";
- #endif
-
- static char nogroup[] = "411 No such newsgroup\n";
- static char noselect[] = "412 No newsgroup selected\n";
- static char nonext[] = "421 No next article\n";
- static char noprev[] = "422 No previous article\n";
- static char noart[] = "430 No such article\n";
- static char notwanted[] = "435 Article not wanted - do not send it\n";
- static char transnotok[] = "437 Article rejected - do not try again\n";
- #ifdef POST_ENBL
- static char noposting[] = "440 Posting not allowed\n";
- static char postfailed[] = "441 Posting failed\n";
- #endif
- static char badsyntax[] = "501 Syntax error\n";
- #if (defined(NNTPRESTRICT) || defined(NNTPLIFETIME))
- static char restriction[] = "502 Access restriction\n";
- #endif
- static char error[] = "503 Command not performed\n";
- static char lowmem[] = "503 System overloaded\n";
- char NEol[] = ".\n";
-
- /* some prototypes */
- static int near
- #ifdef POST_ENBL
- get_article2(struct nntpsv *mp, int command);
- #else
- get_article2(struct nntpsv *mp);
- #endif
-
-
-
- static int near
- strxlen(register char *s)
- {
- register int i = 0;
-
- while(*s++ != '\0')
- i++;
- return i;
- }
-
- /* main message-opening routine
- * returncode: NULLFILE if error; filepointer success */
- static FILE * near
- open_message(struct nntpsv *mp,FILE *f)
- {
- char line[LineLen];
-
- if(f != NULLFILE)
- fclose(f);
-
- sprintf(line,"%s/%u",mp->path,mp->pointer);
-
- if ((f = fopen(line,READ_TEXT)) == NULLFILE)
- usputs(mp->s,noart);
- return f;
- }
-
- /* returncode: -1 error; 1 success; 0 no entry */
- static int near
- get_path(char *group,struct nntpsv *mp)
- {
- FILE *f;
- char line[LineLen], *cp;
-
- if(group == NULLCHAR || mp == NULLNNTPSV
- || (f = open_file(Pointer,READ_TEXT,mp->s,0)) == NULLFILE)
- return -1;
-
- group++;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strcspn(line," ") != strxlen(group))
- continue;
- if (strnicmp(group,line,strxlen(group)) == 0) {
- cp = (strchr(line,' ')) + 1;
- if (mp->path != NULLCHAR)
- xfree(mp->path);
- mp->path = strxdup(cp);
- rip2(mp->path);
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
- /* returncode: -1 if error; 1 success; 0 no pointer */
- static int near
- get_pointer(char *group,struct nntpsv *mp)
- {
- FILE *f;
- char line[LineLen], *p;
-
- if(group == NULLCHAR || mp == NULLNNTPSV
- || (f = open_file(Active,READ_TEXT,mp->s,0)) == NULLFILE)
- return -1;
-
- group++;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strcspn(line," ") != strxlen(group))
- continue;
- if (strnicmp(group,line,strxlen(group))==0) {
- p = strchr(line,' ');
- mp->last = (unsigned)atoi(p);
- mp->first = (unsigned)atoi(strchr(++p,' '));
- mp->pointer = (mp->first > mp->last ) ? 0 : mp->first;
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
- #ifdef CONTROL
- static int near
- docontrol(FILE *f,struct nntpsv *mp)
- {
- struct head *h;
-
- if(f == NULLFILE || mp == NULLNNTPSV
- || (h = (struct head *)mxallocw(sizeof(struct head))) == NULLHEAD))
- return -1;
-
- rewind(f);
- h->subject = h->from = h->reply_to = h->id = NULLCHAR;
-
- for(;;) {
- if ((fgets(mp->buf,LineLen,f)) == NULL)
- break;
- if (check_blank(mp->buf))
- break;
- rip2(mp->buf);
- if (strncmp(mp->buf,subj,9) == 0)
- h->subject = strxdup(mp->buf);
- if (strncmp(mp->buf,frm,6) == 0)
- h->from = strxdup(mp->buf);
- if (strnicmp(mp->buf,reply_to,10) == 0)
- h->reply_to = strxdup(mp->buf);
- if (strnicmp(mp->buf,msgid,12) == 0)
- h->id = strxdup(strchr(mp->buf,'<'));
- }
- if (h->subject != NULLCHAR)
- if (strncmp(h->subject,"Subject: sendme ",16) == 0)
- dosendme(h);
- if (h->subject != NULLCHAR)
- xfree(h->subject);
- if (h->from != NULLCHAR)
- xfree(h->from);
- if (h->reply_to != NULLCHAR)
- xfree(h->reply_to);
- if (h->id != NULLCHAR)
- xfree(h->id);
- xfree((char *)h);
- return 0;
- }
- #endif
-
-
- /***********************************/
- /* handles incoming newnews-cmd */
- /***********************************/
-
- static void near
- donewnews(char *string,struct nntpsv *mp)
- {
- FILE *f;
-
- if((f = temp_file(mp->s,1)) == NULLFILE)
- return;
-
- #if (defined(NNTPRESTRICT) || defined(NNTPLIFETIME))
- switch(newnews(string,mp,f,1)) {
- #else
- switch(newnews(string,mp,f)) {
- #endif
-
- #ifdef NNTPLIFETIME
- case -3: /* user request with unaccept poll date/time */
- #endif
- #ifdef NNTPRESTRICT
- case -2: /* user request: ALL newsgroups */
- #endif
- #if (defined(NNTPRESTRICT) || defined(NNTPLIFETIME))
- usputs(mp->s,restriction);
- break;
- #endif
- case -1: /* error in "newnews" routine */
- usputs(mp->s,badsyntax);
- break;
- case 0: /* no new news */
- usputs(mp->s,newnews_t);
- usputs(mp->s,NEol);
- break;
- default: /* new news available, send news file */
- usputs(mp->s,newnews_t);
- sendfile(f,mp->s,ASCII_TYPE,0);
- usputs(mp->s,NEol);
- break;
- }
- fclose(f);
- return;
- }
-
- /* change current newsgroup
- * returncode: -1 if error; 0 success; 1 no newsgroup */
- static int near
- dogroup(struct nntpsv *mp,char *buf)
- {
- char *p;
- int er = -1;
-
- if((p = strchr(buf,' ')) == NULLCHAR)
- return er;
-
- switch (er = get_path(p,mp)) {
- case 0:
- usputs(mp->s,nogroup);
- er = 1;
- break;
- default:
- p = strchr(buf,' ');
- if (get_pointer(p,mp) == 1) {
- usprintf(mp->s,listarticle,
- mp->last - mp->first + 1,mp->first,mp->last,strchr(buf,' '));
- return 0;
- }
- case -1:
- usputs(mp->s,error);
- break;
- }
- return er;
- }
-
-
- /* checks if newsgroup is selected
- * returncode: -1 no group selected; 0 success */
- static int near
- check_grp(struct nntpsv *mp)
- {
- if(mp == NULLNNTPSV || mp->path == NULLCHAR) {
- usputs(mp->s,noselect);
- return -1;
- }
- return 0;
- }
-
- /* get id-number of message
- * returncode: -1 if error; 0 if no message; 1 success */
- static int near
- get_id(char *bp,struct nntpsv *mp)
- {
- FILE *f;
- char tmp[LineLen];
-
- if ((f = open_message(mp,NULLFILE)) == NULLFILE)
- return 0;
-
- for (;;) {
- if (fgets(tmp,LineLen,f) == NULL)
- break;
- if (check_blank(tmp))
- break;
- if (strnicmp(tmp,msgid,12)==0) {
- fclose(f);
- strcpy(bp,strchr(tmp,' '));
- rip2(bp);
- return 1;
- }
- }
- fclose(f);
- strcpy(bp,"\0");
- return 0;
- }
-
- /* gets next news of newsgroup
- * returncode: -1 if error; 0 no news; 1 success */
- static int near
- get_next(struct nntpsv *mp)
- {
- FILE *f;
-
- for (;;) {
- if (mp->pointer == 0 ) {
- usputs(mp->s,nonext);
- return 0;
- }
- if (++(mp->pointer) > mp->last) {
- mp->pointer--;
- usputs(mp->s,nonext);
- return 0;
- }
- sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
- if ((f = open_file(mp->buf,READ_TEXT,mp->s,0)) != NULLFILE) {
- fclose(f);
- return 1;
- }
- }
- }
-
- /* gets last news of newsgroup
- * returncode: -1 if error; 0 no news; 1 success */
- static int near
- get_last(struct nntpsv *mp)
- {
- FILE *f;
-
- for (;;) {
- if (mp->pointer == 0) {
- usputs(mp->s,noprev);
- return 0;
- }
- if (--(mp->pointer) < mp->first) {
- mp->pointer++;
- usputs(mp->s,noprev);
- return 0;
- }
- sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
- if ((f = open_file(mp->buf,READ_TEXT,mp->s,0)) != NULLFILE) {
- fclose(f);
- return 1;
- }
- }
- }
-
- static int near
- art_ret(struct nntpsv *mp,char flag)
- {
- if(get_id(mp->buf,mp) < 1)
- return -1;
- if(flag)
- usprintf(mp->s,retrieve,mp->pointer,mp->buf,artmsg);
- return 0;
- }
-
- /* Sends article <message-id> to the client or check if host in path
- * we are polling now, already exists.
- * Return value: -1 on error, 1 article sent, 0 no article
- * flag = 1 : check only pathfield in article
- * flag = 0 : send article
- */
- int
- doarticle(char *buf,struct nntpsv *mp,char flag, char *hname)
- {
- FILE *f;
- char *p, *p2, *holds, line[LineLen];
- int32 ok = 0;
-
- if((p = strchr(buf,'<')) == NULLCHAR
- || (f = fopen(History,READ_TEXT)) == NULLFILE) {
- usputs(mp->s,badsyntax);
- return -1;
- }
- while(fgets(line,LineLen,f),!feof(f)) {
- if (strstr(line,p) != NULLCHAR) {
- fclose(f);
- p = (strchr(line,' ')) + 14; /* pointer to the first newsgroup */
- p2 = strchr(p,'/'); /* pointer to article number */
- mp->hold_i = mp->pointer; /* save current pointer */
- holds = strxdup(mp->path); /* save path of current article */
- mp->pointer = atoi((p2 + 1)); /* get the article number */
-
- if (mp->path != NULLCHAR) {
- xfree(mp->path);
- mp->path='\0';
- }
-
- *p2 = '\0';
- rip2(p);
-
- if (strncmp(p+1,"JUNK",6) == 0) {
- sprintf(mp->buf,"%s",Forward);
- mp->path = strxdup(mp->buf);
- } else
- get_path(p,mp);
-
- if(hname == NULLCHAR ) {
- /* send article */
- if ((f = open_message(mp,f)) == NULLFILE) {
- xfree(mp->path); /* file not found */
- mp->path = strxdup(holds);
- mp->pointer = mp->hold_i;
- xfree(holds);
- return -1;
- }
- if(art_ret(mp,flag) != -1) {
- ok = sendfile(f, mp->s, ASCII_TYPE,0);
- ok = (ok == -1) ? -1 : 1;
- usputs(mp->s,NEol);
- }
- }
- else { int getpath = 0;
- /* check only pathfield in article */
- sprintf(line,"%s/%u",mp->path,mp->pointer);
- if ((f = fopen(line,READ_TEXT)) == NULLFILE) {
- xfree(mp->path); /* file not found */
- mp->path = strxdup(holds);
- mp->pointer = mp->hold_i;
- xfree(holds);
- return -1;
- }
-
- while (!getpath && (fgets(line,LINELEN,f),!feof(f))){
- if (strnicmp(line,pth,6) != 0)
- continue;
- ok = 1; /* default: send article */
- getpath = 1; /* reset condition for while-loop */
-
- /* skip first entry, because its our own hostname */
- p2 = strstr(line,"!") + 1;
-
- for (;;) {
- /* cut off first entry and compare it with the hostname */
- if ((p = strstr(p2,"!")) == NULL)
- break;
- *p='\0';
- if (strcmpi(hname,p2) == 0) {
- ok = 0; /* oops, I've got you. */
- break; /* don't forward article */
- }
- p2 = ++p;
- }
- }
- }
- fclose(f);
- xfree(mp->path);
- mp->path = strxdup(holds);
- mp->pointer = mp->hold_i;
- xfree(holds);
- return ((int)ok);
- }
- }
- fclose(f);
- usputs(mp->s,noart);
- return 0;
- }
-
-
- static int near
- set_pointer(struct nntpsv *mp, char *buf)
- {
- char *cp;
-
- if((cp = strpbrk(buf,"0123456789")) != NULLCHAR) {
- int cnt = atoi(cp);
- if ((cnt > mp->last) || ( cnt < mp->first)) {
- usputs(mp->s,noart);
- return -1;
- }
- mp->pointer = cnt;
- }
- return 0;
- }
-
- static void
- nntpserv(int s, void *unused, void *p) {
- struct nntpsv *mp;
- struct tm *ltm;
- FILE *fp;
- long t;
- int cnt;
- char **cmdp, *arg, *cp, *cmd, buf[LineLen];
- #ifdef LZW
- int lbits, lmode;
- #endif
- #ifdef XHEADER
- char *cp2;
- int first, last;
- #endif
-
- /* Command table */
- char *commands[] = {
- "quit",
- #define QUIT_CMD 0
- "help",
- #define HELP_CMD 1
- "list",
- #define LIST_CMD 2
- "group",
- #define GROUP_CMD 3
- "debug",
- #define DEBUG_CMD 4
- "article",
- #define ARTICLE_CMD 5
- "next",
- #define NEXT_CMD 6
- "xinfo",
- #define XINFO_CMD 7
- "ihave",
- #define IHAVE_CMD 8
- "newnews",
- #define NEWNEWS_CMD 9
- "head",
- #define HEAD_CMD 10
- "body",
- #define BODY_CMD 11
- "stat",
- #define STAT_CMD 12
- "last",
- #define LAST_CMD 13
- "slave",
- #define SLAVE_CMD 14
- "xlzw",
- #define XLZW_CMD 15
-
- #if (defined(XHEADER) && defined(POST_ENBL))
- "post",
- #define POST_CMD 16
- "xhdr",
- #define XHDR_CMD 17
-
- #elif (defined(XHEADER))
- "xhdr",
- #define XHDR_CMD 16
-
- #elif (defined(POST_ENBL))
- "post",
- #define POST_CMD 16
-
- #endif
- NULLCHAR
- };
-
- sockmode(s,SOCK_ASCII);
- sockowner(s,Curproc); /* We own it now */
-
- if (!Filecheck)
- if(check_system()) {
- usprintf(s,fatal,"STRUCTURE");
- close_s(s);
- return;
- }
-
- if((mp = (struct nntpsv *)mxallocw(sizeof(struct nntpsv))) == NULLNNTPSV) {
- usprintf(s,Nospace);
- close_s(s);
- return;
- }
- mp->s = s;
- log(mp->s,"NNTP open");
- mp->debug = 0;
- mp->id = mp->path = mp->newnews = NULLCHAR;
-
- time(&t);
- ltm = gmtime(&t);
- cp = asctime(ltm); /* nntp time always GMT */
- cp[24] = '\0';
-
-
-
- #ifdef POST_ENBL
- usprintf(mp->s,nnversion,postingok ? '0' : '1', Hostname,Version,cp,
- postingok ? "ok" : "not allowed");
- #else
- usprintf(mp->s,nnversion,Hostname,Version,cp);
- #endif
-
- if(++Nntpsessions > Nntpmaxcli) {
- usputs(mp->s,lowmem);
- goto quit;
- }
-
- loop:
- if ((cnt = recvline(mp->s,buf,LineLen)) == -1) {
- /* He closed on us */
- goto quit;
- }
- rip2(buf);
- cmd = buf;
-
- /* Translate entire buffer to lower case */
- for(cp = cmd; *cp != '\0' && *cp != ' ' ;cp++) {
- *cp = tolower(*cp);
- }
- /* Find command in table; if not present, return syntax error */
- for(cmdp = commands; *cmdp != NULLCHAR; cmdp++)
- if(strnicmp(*cmdp,cmd,strxlen(*cmdp)) == 0)
- break;
-
- if(*cmdp == NULLCHAR){
- usputs(mp->s,badsyntax);
- goto loop;
- }
- arg = &cmd[strxlen(*cmdp)];
-
- /* Skip spaces after command */
- while(*arg == ' ')
- arg++;
-
- /* Execute specific command */
- switch((int)(cmdp - commands)) {
- case XLZW_CMD:
- #ifdef LZW
- if (LzwActive) {
- usprintf(mp->s,transok);
- cp = strchr(arg,' ');
- *cp++ = '\0';
- lbits = atoi(arg); /*get lzwbits*/
- lmode = atoi(cp);
- lzwinit(mp->s,lbits,lmode);
- } else
- #endif
- usprintf(mp->s,error);
- break;
- case QUIT_CMD:
- usputs(mp->s,closing);
- goto quit;
- case NEWNEWS_CMD:
- if ((cp = strchr(buf,' ')) == NULLCHAR)
- usputs(mp->s,badsyntax);
- else
- donewnews(++cp,mp);
- break;
- case IHAVE_CMD:
- if ((cp = strchr(buf,'<')) == NULLCHAR)
- usputs(mp->s,badsyntax);
- else if (check_article(cp) == 1)
- usputs(mp->s,notwanted);
- else {
- usputs(mp->s,sendart);
- #ifdef POST_ENBL
- get_article2(mp,IHAVE_CMD);
- #else
- get_article2(mp);
- #endif
- }
- break;
- #ifdef POST_ENBL
- case POST_CMD :
- if (postingok) {
- usputs(mp->s,sendpost);
- get_article2(mp,POST_CMD);
- }
- else
- usputs(mp->s,noposting);
- break;
- #endif
- case HELP_CMD:
- usprintf(mp->s,"100-%s - help follows\n",Hostname);
- if ((fp = fopen(Nhelp,READ_TEXT)) != NULLFILE ) {
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- } else
- usputs(mp->s,help);
- usputs(mp->s,NEol);
- break;
- case XINFO_CMD:
- if ((fp = fopen(NInfo,READ_TEXT)) != NULLFILE ) {
- usprintf(mp->s,"100-%s - info follows\n",Hostname);
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- } else
- usputs(mp->s,xinfo);
- usputs(mp->s,NEol);
- break;
- case LIST_CMD:
- if ((fp = open_file(Active,READ_TEXT,mp->s,0)) != NULLFILE) {
- usputs(mp->s,listgrps);
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- usputs(mp->s,NEol);
- } else
- usputs(mp->s,noactive);
- break;
- case GROUP_CMD :
- if(dogroup(mp,&buf[0]) == -1)
- usputs(mp->s,badsyntax);
- break;
- case HEAD_CMD :
- if (check_grp(mp))
- break;
- if(set_pointer(mp,buf))
- break;
- if (get_id(mp->buf,mp) == 0)
- break;
- usprintf(mp->s,head,mp->pointer,mp->buf,artmsg);
- if ((fp = open_message(mp,fp)) != NULLFILE) {
- for (;;) {
- if ((fgets(mp->buf,LineLen,fp)) == NULL)
- break;
- if (check_blank(mp->buf))
- break;
- usputs(mp->s,mp->buf);
- }
- fclose(fp);
- }
- usputs(mp->s,NEol);
- break;
- case BODY_CMD :
- if (check_grp(mp))
- break;
- if(set_pointer(mp,buf))
- break;
- if (get_id(mp->buf,mp) == 0)
- break;
- usprintf(mp->s,body,mp->pointer,mp->buf,artmsg);
- if ((fp = open_message(mp,fp)) != NULLFILE) {
- mp->hold_i = 0;
- for (;;) {
- if ((fgets(mp->buf,LineLen,fp)) == NULL)
- break;
- if (mp->hold_i)
- usputs(mp->s,mp->buf);
- if (check_blank(mp->buf))
- mp->hold_i = 1;
- }
- fclose(fp);
- }
- usputs(mp->s,NEol);
- break;
- case STAT_CMD :
- if (check_grp(mp))
- break;
- if(set_pointer(mp,buf))
- break;
- if (get_id(mp->buf,mp) == 0)
- break;
- usprintf(mp->s,statistics,mp->pointer,mp->buf,artmsg);
- break;
- case ARTICLE_CMD :
- if (strchr(buf,'<') != NULLCHAR) {
- doarticle(buf,mp,1,NULLCHAR);
- break;
- }
- if (check_grp(mp))
- break;
- cp = strchr(buf,'e') + 1;
-
- if ((cnt > 8) && !(check_blank(cp))) {
- if(set_pointer(mp,buf))
- break;
- }
- if ((fp = open_message(mp,fp)) != NULLFILE) {
- art_ret(mp,1);
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- usputs(mp->s,NEol);
- }
- break;
- case NEXT_CMD :
- if (check_grp(mp))
- break;
- if (get_next(mp) == 1) {
- if (get_id(buf,mp) == 1)
- usprintf(mp->s,sepcmd,mp->pointer,&buf[1],artmsg);
- break;
- }
- break;
- case LAST_CMD :
- if (check_grp(mp))
- break;
- if (get_last(mp) == 1 ) {
- if (get_id(buf,mp) == 1)
- usprintf(mp->s,sepcmd,mp->pointer,&buf[1],artmsg);
- break;
- }
- break;
- #ifdef XHEADER
- case XHDR_CMD:
-
- /* test if group is selected */
- if (check_grp(mp))
- break;
-
- /* set pointer to headerfield */
- if ( (cp = strchr(buf,' ')) == NULLCHAR) {
- usputs(mp->s,badsyntax);
- break;
- }
-
- /* set pointer to article range */
- if ( (cp2 = strchr(++cp,' ')) == NULLCHAR)
- /* no article range specified */
- first = last = mp->pointer;
- else {
- *cp2++ = '\0';
- /* get first article number */
- if (!isdigit(*cp2)) {
- usputs(mp->s,badsyntax);
- break;
- }
- else
- first = atoi(cp2);
-
- if (first < mp->first)
- first = mp->first;
- else {
- if (first > mp->last)
- first = mp->last;
- }
-
-
- /* get last number */
- if ((cp2 = strchr(cp2,'-')) == NULLCHAR)
- last = first;
- else {
- if (!isdigit(*(++cp2)))
- last = mp->last;
- else
- last = ( (cnt = atoi(cp2)) > mp->last) ? mp->last : cnt;
- }
- }
-
- if (last < first)
- last = first;
-
- /* send response */
- usprintf(mp->s,extrfoll,strupr(cp));
-
- /* add a colon to headerfield */
- cp = strcat(cp,":");
-
- /* now we are looking for headerfield in specified articlerange */
- for (cnt = first; cnt <= last; cnt++) {
- char line[LineLen];
-
- mp->pointer = cnt;
- sprintf(line,"%s/%u",mp->path,mp->pointer);
- if ( (fp = fopen(line,READ_TEXT)) == NULLFILE)
- continue;
- for (;;) {
- if ((fgets(mp->buf,LineLen,fp)) == NULL)
- break;
- if (check_blank(mp->buf)) {
- usprintf(mp->s,"%d (none)\n",cnt);
- break;
- }
- if (strncmpi(cp,mp->buf,strlen(cp)) == NULL) {
- cp2 = strchr(mp->buf,':') + 1;
- *cp2++ = '\0';
- usprintf(mp->s,"%d %s",cnt,cp2);
- break;
- }
- }
- fclose(fp);
- }
- usputs(mp->s,NEol);
- break;
- #endif
- /* This two following cmds currently are not used for much */
- case DEBUG_CMD:
- mp->debug = (mp->debug == 0) ? 1 : 0;
- usprintf(mp->s,debug,(mp->debug == 0) ? "OFF" : "ON");
- break;
- case SLAVE_CMD :
- mp->slave = (mp->slave == 0) ? 1 : 0;
- usprintf(mp->s,slave,(mp->slave == 0) ? "OFF" : "ON");
- break;
- }
- goto loop;
-
- quit:
-
- log(mp->s,"NNTP close");
- close_s(s);
-
- Nntpsessions--;
-
- if(mp->path != NULLCHAR)
- xfree(mp->path);
- if(mp->newnews != NULLCHAR)
- xfree(mp->newnews);
- xfree(mp);
- }
-
-
- /* returncode: -1 if error; 0 success */
- static int near
- #ifdef POST_ENBL
- get_article2(struct nntpsv *mp, int command)
- #else
- get_article2(struct nntpsv *mp)
- #endif
- {
- FILE *f;
- int ret = -1;
-
- if(mp == NULLNNTPSV || (f = temp_file(0,1)) == NULLFILE)
- return -1;
-
- if(recv_file(f,mp->s) != -1) {
- char *cp;
- int foundmid = 0;
-
- /* get id-number from article, not from IHAVE offer */
- rewind(f);
- while(fgets(mp->buf,LineLen,f),!feof(f)) {
- rip2(mp->buf);
- if (strnicmp(mp->buf,msgid,12) == 0) {
- if ((cp = strchr(mp->buf,'<')) != NULLCHAR) {
- mp->id = strxdup(cp);
- foundmid = 1;
- break;
- }
- }
- }
- /* minimum header in article required !
- Now check again, if same news exists in history */
- if (foundmid == 1 && check_article(mp->id) == 0 && garbled(f) == 0) {
- rewind(f);
- ret = xfer_article2(f,mp);
- }
- else if (foundmid) {
- xfree(mp->id);
- }
- }
- fclose(f);
- #ifdef POST_ENBL
- if (command == POST_CMD)
- usputs(mp->s,ret ? postfailed : postok);
- else
- usputs(mp->s,ret ? transnotok : transok);
- #else
- usputs(mp->s,ret ? transnotok : transok);
- #endif
- return ret;
- }
-
-
- /* ---------------------------- SMTP->NNTP-GATE --------------------------- */
- int
- nnGpost(FILE *data,char *from,struct list *le)
- {
- FILE *f;
- struct nntpsv *mp;
- int msgidfound = 0;
- char buf[LineLen], *cp, *cp1, *cp2, *revpath;
-
- if (!Filecheck)
- if(check_system())
- return -1;
-
- if ((f = temp_file(0,1)) == NULLFILE)
- return -1;
-
- mp = (struct nntpsv *)mxallocw(sizeof(struct nntpsv));
-
- /* build path field (dg1zx) */
-
- /* cp is used to generate FROM field */
- cp = strxdup(from);
- if((cp1 = strpbrk(cp,"@. ")) != NULLCHAR)
- *cp1 = '\0';
-
- /* cp2 is used to copy reverse path */
- cp2 = strxdup(cp);
- revpath = mxallocw(strlen(cp2)+1);
- *revpath = '\0';
-
- while ((cp1 = strrchr(cp2,'%')) != NULL) {
- *cp1++ = '\0';
- strcat(revpath,cp1);
- strcat(revpath,"!");
- }
-
- strcat(revpath,cp2);
- fprintf(f,"%s%s\n",pth,revpath);
-
- xfree(revpath);
- xfree(cp2);
-
-
- /* look for msg-id */
- rewind(data);
- while(fgets(buf,LineLen,data) != NULL) {
- if(*buf == '\t' || *buf == ' ')
- continue;
- rip(buf);
- if(*buf == '\0')
- break;
- if(htype(buf) == MSGID) {
- msgidfound = 1;
- break;
- }
- }
-
- /* reorganize header */
- rewind (data);
- while(fgets(buf,LineLen,data) != NULL) {
- if(*buf == '\t' || *buf == ' ')
- continue;
- rip(buf);
- if(*buf == '\0')
- break;
- switch(htype(buf)) {
- case FROM:
- /* generating from line */
- fprintf(f,"%s%s@%s",frm,cp,Hostname);
- if((cp1 = strpbrk(buf,"<(")) != NULLCHAR)
- fprintf(f," %s",cp1);
-
- /* generating newsgroups line */
- if((cp1 = strpbrk(&le->val[1],"!@")) != NULLCHAR)
- *cp1 = '\0';
- fprintf(f,"\n%s%s\n",ngrps,&le->val[1]); /* skip the bang */
- continue;
- case SUBJECT:
- fprintf(f,"%s\n",strxlen(buf) < 10 ? "Subject: (none)" : buf);
- if(msgidfound == 0) {
-
- sprintf(mp->buf,"<%ld@%s>",get_msgid(),Hostname);
- fprintf(f,"%s%s\n",msgid,mp->buf);
- mp->id = strxdup(mp->buf);
- }
- fprintf(f,"Sender: NNTP@%s\n",Hostname);
- continue;
- case MSGID:
- if(msgidfound == 1) {
- fprintf(f,"%s\n",buf);
- if((cp1 = strchr(buf,'<')) != NULLCHAR) {
- sprintf(mp->buf,"%s",cp1);
- mp->id = strxdup(cp1);
- }
- }
- continue;
- case TO:
- case RECEIVED:
- case SENDER:
- case STATUS:
- case NOHEADER:
- continue;
- }
- fprintf(f,"%s\n",buf);
- }
-
- xfree(cp);
-
- fputc('\n',f);
-
- while(fgets(buf,sizeof(buf),data) != NULL)
- fputs(buf,f);
-
- fflush(f);
- rewind(f);
- xfer_article2(f,mp);
- fclose(f);
- xfree(mp);
- return 0;
- }
-
- /* ---------------------------- Servercmd --------------------------- */
-
- /* Start up NNTP receiver service */
- int
- nntp1(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct sockaddr_in lsocket;
- int s;
-
- if(Snntp != -1 || check_system() == -1)
- return -1;
-
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"NNTP listener");
-
- lsocket.sin_family = AF_INET;
- lsocket.sin_addr.s_addr = INADDR_ANY;
- lsocket.sin_port = (argc < 2) ? IPPORT_NNTP : atoi(argv[1]);
-
- Snntp = socket(AF_INET,SOCK_STREAM,0);
- bind(Snntp,(char *)&lsocket,sizeof(lsocket));
- listen(Snntp,1);
-
- for(;;){
- if((s = accept(Snntp,NULLCHAR,(int *)NULL)) == -1)
- break; /* Service is shutting down */
-
- if(availmem() < Memthresh){
- usputs(s,lowmem);
- shutdown(s,1);
- } else {
- sockmode(s,SOCK_ASCII);
- /* Spawn a server */
- newproc("NNTP server",4048,nntpserv,s,NULL,NULL,0);
- }
- }
- return 0;
- }
-
- /* Shutdown NNTP service (existing connections are allowed to finish) */
- int
- nntp0(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Snntp);
- Snntp = -1;
- return 0;
- }
-
- #endif /* NNTP */
-